#ifndef __BED_WARS_H__
#define __BED_WARS_H__

#include "Server/IPlugin.h"
#include "InventoryEvent.h"
#include "PlayerEvent.h"
#include "SignEvent.h"
#include "Engine/Point3.hpp"
#include "Engine/Point2.hpp"
#include "Engine/Vector3.hpp"
#include <cstdint>
#include <vector>
#include <unordered_map>
#include "entt/entity/entity.hpp"
#include <set>
#include <mutex>
#include "TeamType.h"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentPlayer;
}

namespace BedWars
{
    
    class SubsystemBedWarsTerrain;
    class SubsystemBedWars;
    struct TeamData
    {
        // TeamType teamType;                     // 队伍类型
        Point3 joinSignPoint;                   // 加入的牌子位置
        Vector3 startPosition;                  // 复活点或开始点的位置      
        Point3 bedPoint;                        // 床的位置
        std::vector<entt::entity> playerVec;    // 队伍表
    };

    class BedWarsCore : public PocketSurvival::IPlugin
    {
    private:
        InventoryEvent *m_inventoryEvent = nullptr;
        PlayerEvent *m_playerEvent = nullptr;
        SignEvent *m_signEvent = nullptr;

        std::mutex m_setRanksHomeMutex;
        std::unordered_map<uint16_t, TeamType> m_setTeamHomeMap;

    public:
        // 是否处于编译模式
        bool isEditMode = true;

        int32_t limitHeight = -128;
        Point2 limitCoordStart = Point2(-128, -128);
        Point2 limitCoordEnd = Point2(128, 128);


        // 一个队伍的最大人数
        uint8_t teamPlayerCount;
        // 床需要破坏几次
        uint8_t bedBreakCount;
        // 玩家一开始的出生点
        Vector3 respawnPosition;
        // 队伍的基本数据
        TeamData teamData[4];

        std::mutex resourceSetMutex;
        std::set<Point3> resourceSet;


        SubsystemBedWarsTerrain *bedWarsTerrain;
        SubsystemBedWars *subsystemBedWars;

    public:
        BedWarsCore();
        virtual const std::string &getPluginName() override;
        virtual const std::string &getIntroduce() override;
        virtual uint32_t getUseAuthLevel() override;
        virtual AuthDisplayType getDisplayType() override;
        virtual void processCmd(ChatObj &chatObj, std::vector<std::string> &cmdDataVec) override;

        virtual void getCmds(std::vector<std::string> &cmdVec) override;
        virtual void load() override;
        virtual void save() override;

        inline TeamType getSetTeamHomeType(entt::entity entity);
        inline void addResourcePoint(const Point3 &point);
        inline void removeResourcePoint(const Point3 &point);

    };
    
    inline TeamType BedWarsCore::getSetTeamHomeType(entt::entity entity)
    {
        std::lock_guard<std::mutex> lk(m_setRanksHomeMutex);
        auto it = m_setTeamHomeMap.find((uint16_t)entity);
        if(it != m_setTeamHomeMap.end())
        {
            return it->second;
        }
        return TeamType::None;
    }

    inline void BedWarsCore::addResourcePoint(const Point3 &point)
    {
        std::lock_guard<std::mutex> lk(resourceSetMutex);
        resourceSet.insert(point);
    }

    inline void BedWarsCore::removeResourcePoint(const Point3 &point)
    {
        std::lock_guard<std::mutex> lk(resourceSetMutex);
        auto it = resourceSet.find(point);
        if(it != resourceSet.end())
        {
            resourceSet.erase(it);
        }
    }

    
} // namespace BedWars

#endif
